import * as THREE from "three"
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
import BatchTable from "../utils/BatchTable"
import FeatureTable from "../utils/FeatureTable"
function _(e) {
  return new TextDecoder().decode(e)
}

class B3DMLoaderBase {
  fetchOptions: any
  workingPath: string
  constructor() {
    ;(this.fetchOptions = {}), (this.workingPath = "")
  }
  load(e) {
    return fetch(e, this.fetchOptions)
      .then(t => {
        if (!t.ok) throw new Error(`Failed to load file "${e}" with status ${t.status} : ${t.statusText}`)
        return t.arrayBuffer()
      })
      .then(t => {
        if ("" === this.workingPath) {
          const t = e.split(/\\\//g)
          t.pop(), (this.workingPath = t.join("/"))
        }
        return this.parse(t)
      })
  }
  parse(e) {
    const t = new DataView(e),
      r = String.fromCharCode(t.getUint8(0)) + String.fromCharCode(t.getUint8(1)) + String.fromCharCode(t.getUint8(2)) + String.fromCharCode(t.getUint8(3))
    console.assert("b3dm" === r)
    const s = t.getUint32(4, !0)
    console.assert(1 === s)
    const n = t.getUint32(8, !0)
    console.assert(n === e.byteLength)
    const i = t.getUint32(12, !0),
      o = t.getUint32(16, !0),
      a = t.getUint32(20, !0),
      l = t.getUint32(24, !0),
      c = e.slice(28, 28 + i + o),
      h = new FeatureTable(c, 0, i, o),
      u = 28 + i + o,
      d = e.slice(u, u + a + l),
      p = new BatchTable(d, h.getData("BATCH_LENGTH"), 0, a, l),
      f = u + a + l
    return {
      version: s,
      featureTable: h,
      batchTable: p,
      glbBytes: new Uint8Array(e, f, n - f)
    }
  }
}
export default class B3DMLoader extends B3DMLoaderBase {
  manager: THREE.LoadingManager

  constructor(e = THREE.DefaultLoadingManager) {
    super(), (this.manager = e)
  }
  parse(e): any {
    const t = super.parse(e),
      r = t.glbBytes.slice().buffer
    return new Promise((e, s) => {
      const n = this.manager,
        i = this.fetchOptions,
        o: any = n.getHandler("path.gltf") || new GLTFLoader(n)
      "include" === i.credentials && "cors" === i.mode && o.setCrossOrigin("use-credentials"),
        "credentials" in i && o.setWithCredentials("include" === i.credentials),
        i.headers && o.setRequestHeader(i.headers)
      let a = this.workingPath
      ;/[\\/]$/.test(a) || (a += "/"),
        o.parse(
          r,
          a,
          r => {
            const { batchTable: s, featureTable: n } = t,
              { scene: i } = r,
              o = n.getData("RTC_CENTER")
            o && ((i.position.x += o[0]), (i.position.y += o[1]), (i.position.z += o[2])),
              (r.batchTable = s),
              (r.featureTable = n),
              (i.batchTable = s),
              (i.featureTable = n),
              e(r)
          },
          s
        )
    })
  }
}
